home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / WINDOWS / LZAPI.ZIP / BCKUP.ZIP / BCKUP.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-03-21  |  15.5 KB  |  525 lines

  1. {----------------------------------------------------------------------*
  2.  *
  3.  *    B C K U P . P A S -     Dipl. Ing. Bernd Herd
  4.  *                Heidelberger Landstr. 316
  5.  *                64297 Darmstadt
  6.  *                Germany
  7.  *                Tel./Fax: 06151 / 591216
  8.  *    (C) 1994-95 Bernd Herd
  9.  *
  10.  * WLHA.DLL Dynamic Link Library for Microsoft Windows 3.1
  11.  * makes it possible to extract Files from and add Files to LHA-Archives
  12.  * without using LHA.EXE
  13.  *
  14.  * This is a Demonstration Program to show you, how a simple
  15.  * Backup-Solution may work with WLHA.DLL. It is not intended to
  16.  * be a professional Backup Program.
  17.  *
  18.  * You may want to Copy the RC-Resource Files via the Dos-Command-
  19.  * line BRC -R BCKUP.RC before Compiling this Pascal-Program in the IDE.
  20.  *
  21.  * What does this Demo-Program Do?
  22.  * 1. It let's you select some files that shall be compressed
  23.  * 2. When Pressing OK, it will begin to Compress all the selected
  24.  *    Files in one big Temporary Archiv
  25.  * 3. Afterwards it distributes the Big temporary Archiv onto the
  26.  *    Count of Diskettes needed
  27.  * 4. It will add a restore.BAT-Batchfile that can be used to
  28.  *    restore the Files backuped
  29.  *
  30.  *---------------------------------------------------------------}
  31. {$X+}
  32.  
  33. Uses WLHa,                          { Yeah! }
  34.  
  35.      Objects,                       { For TCollection }
  36.      WinDos,                        { For FindFirst }
  37.      WinTypes, WinAPI, WinProcs, Win31,
  38.      OWindows, ODialogs,            { OWL }
  39.      BckUpr,                        { Ressource IDs }
  40.      CommDlg,                       { File File Selection Dialog Box }
  41.      Strings,
  42.      ShellApi,                      { For Drag & Drop Support }
  43.      Ms3d;                          { Let's look a little bit less boring }
  44.  
  45.  
  46. { ----------- Let's define a Simple File-Name-Container ------------ }
  47. type PTFile= ^TFile;                         { File Attributes for the Container }
  48.      TFile = object
  49.        Name : Array[0..120] of Char;
  50.        constructor Init( AFile : PChar );
  51.        destructor  Done;
  52.      End;
  53.  
  54.      PTFileList = ^TFileList;
  55.      TFileList = object(TCollection)
  56.      End;
  57.  
  58.  
  59. constructor TFile.Init( AFile : PChar );
  60. Begin
  61.      strcopy(Name, AFile);
  62. End;
  63.  
  64. destructor  TFile.Done;
  65. Begin
  66. End;
  67.  
  68. { ----- It's a good Idea to have a Window in a Windows-Program ---- }
  69.  
  70. type
  71.    TApp = object(TApplication)
  72.    procedure InitMainWindow; virtual;
  73. end;
  74.  
  75. type PTBckup = ^TBckup;
  76.      TBckup  = object(TDialog)
  77.      Liste : PListBox;
  78.  
  79.      procedure SetupWindow; virtual;
  80.  
  81.      procedure IdAdd    (var Msg: TMessage)  ; virtual ID_FIRST + IDADD;
  82.      procedure Ok       (var Msg: TMessage)  ; virtual ID_FIRST + IDOK;
  83.      procedure WMDropFiles(var Msg: TMessage)  ; virtual WM_FIRST + WM_DROPFILES;
  84.  
  85.      procedure FilesFromCommandLine;
  86.      procedure FilesFromCommDlg;
  87.  
  88.      procedure CopyToDiskette(FName : PChar);
  89.  
  90.      End;
  91.  
  92.      PAbort = ^TAbort;
  93.      TAbort = object(TDialog)
  94.      procedure Cancel   (var Msg: TMessage)  ; virtual ID_FIRST + IDCANCEL;
  95.      End;
  96.  
  97.  
  98. {$R bckup.res}
  99.  
  100. procedure TApp.InitMainWindow;
  101. begin
  102.    MainWindow := New(PTBckup, init(nil,'DEMO'));
  103.    SetKBHandler(MainWindow);
  104. end;
  105.  
  106.  
  107.  
  108.  
  109. { ----------------- Global Variables ------------------------ }
  110. var SourceFiles : TFileList;
  111.  
  112.  
  113.  
  114. { - FilesFromCommandLine -------------------------------------
  115.   Take the list of Files from the given Command Line
  116. }
  117. procedure TBckup.FilesFromCommandLine;
  118. var  ParamNo : Integer;
  119.      ff      : TSearchRec;
  120.      NextName: String[120];
  121.      Dir     : Array[0..100] of char;
  122.      Name    : Array[0..10]  of char;
  123.      Ext     : Array[0..5]   of char;
  124.      NewName : Array[0..120] of char;
  125. Begin
  126.    for ParamNo:=1 to ParamCount do Begin
  127.      { Extract Directory (if any) to be joined to Wildcard search result again }
  128.      NextName:= ParamStr(ParamNo);
  129.      strpcopy(NewName, NextName );
  130.  
  131.      FileSplit( NewName, Dir, Name, Ext);
  132.  
  133.      { Find Files and allow for Wildcards }
  134.      findfirst( NewName, 0, ff);
  135.      Liste^.AddString(NewName);
  136.  
  137.      while DosError = 0 do Begin
  138.         { Join Wildcard search result and Pathname }
  139.         strcopy(NewName, Dir);
  140.         strcat (NewName, ff.Name);
  141.  
  142.         { Include FULL Pathname }
  143.         fileExpand(NewName, NewName);
  144.  
  145.         { Add File to my Container Object }
  146.         Liste^.AddString(NewName);
  147.         SourceFiles.Insert( new (PTFile, Init(NewName) ) );
  148.  
  149.         { Find the next File that matches our specifications }
  150.         findnext(ff);
  151.      End;
  152.    End;
  153. End;
  154.  
  155.  
  156. { - FilesFromCommDlg ---------------------------------------------------
  157.   Let's give the User a Chance to Hack in some more Files via the
  158.   Common Dialogs Interface }
  159. procedure TBckup.FilesFromCommDlg;
  160. var ofn        : TOpenFileName;
  161.     FilesTable ,                       { Pointer to a  Buffer for the File Names }
  162.     ThisFile   ,
  163.     NextFile   : PChar;                { Pointer to the next File }
  164.     Dir        : array[0..120] of char;
  165.     FullName   : array[0..120] of char;
  166. Begin
  167.   GetMem(FilesTable, 32767);
  168.   strcopy(FilesTable, '*.*');
  169.  
  170.   FillChar(ofn, sizeof(ofn), 0);
  171.  
  172.   ofn. lStructSize := sizeof(ofn);
  173.   ofn. hWndOwner   := HWindow;
  174.   ofn. lpstrFilter := 'All Files (*.*)'#0'*.*'#0'Data Base Files(*.db*)'#0'*.db*;*.md*'#0;
  175.   ofn. nFilterIndex:= 1;
  176.   ofn. lpstrFile   := FilesTable;
  177.   ofn. lpstrTitle  := 'Select the Files you wish to backup';
  178.   ofn. Flags       := OFN_FILEMUSTEXIST or OFN_ALLOWMULTISELECT;
  179.   ofn. nMaxFile    := 32767;
  180.  
  181.   if (GetOpenFileName(ofn)) then Begin
  182.     NextFile := strpos(FilesTable, ' ');
  183.     if NextFile<>NIL Then Begin
  184.       NextFile^:=#0;
  185.       Inc(NextFile);
  186.       strcopy(Dir, FilesTable);
  187.  
  188.       while (NextFile<>NIL) Do Begin
  189.          ThisFile := NextFile;
  190.          NextFile := strpos(ThisFile, ' ');
  191.          if (NextFile<>NIL) Then begin
  192.              NextFile^:=#0;
  193.              Inc(NextFile);
  194.          End;
  195.          strcopy(FullName, Dir);
  196.          strcat (FullName, '\');
  197.          strcat (FullName, ThisFile);
  198.  
  199.          Liste^.AddString(FullName);
  200.          SourceFiles.Insert( new (PTFile, Init(FullName) ) );
  201.       End;
  202.     End
  203.   else
  204.     Begin
  205.         SourceFiles.Insert( new (PTFile, Init(FilesTable) ) );
  206.         Liste^.AddString(FilesTable);
  207.     End;
  208.   End;
  209.  
  210.  
  211.   FreeMem(FilesTable, 32767);
  212. End;
  213.  
  214.  
  215.  
  216. procedure TBckUp.IdAdd(var Msg: TMessage);
  217. Begin
  218.    FilesFromCommDlg;
  219. End;
  220.  
  221.  
  222. procedure TBckUp.WMDropFiles(var Msg: TMessage);
  223. var HDrop : THandle;             { File Managers Drop-Handle }
  224.     News  : Integer;             { Count of New Files }
  225.     i     : Integer;
  226.     TheName : Array[0..144] of char;
  227. Begin
  228.   HDrop := Msg.WParam;
  229.   News  := DragQueryFile(HDrop, $FFFF, NIL, 0);
  230.  
  231.   for i:=0 to News-1 do Begin
  232.      DragQueryFile(HDrop, i, TheName, sizeof(TheName) );
  233.      SourceFiles.Insert( new (PTFile, Init(TheName) ) );
  234.      Liste^.AddString(TheName);
  235.   End;
  236.  
  237.   DragFinish(hDrop);
  238. End;
  239.  
  240.  
  241.  
  242.  
  243. const Reserve = $F000;                  { Reserved Space for every Diskette }
  244.  
  245. type HFILE = Integer;
  246.  
  247.  
  248. procedure CopyFileToDiskette(TmpFil : HFile; TmpSize : LongInt; DiskNo : Integer; BlkSize : LongInt );
  249. var cnt, i : Integer;
  250.     result : Word;
  251.     Outf   : HFile;
  252.     fname  : Array[0..120] of char;
  253.     DiskNoStr: Array[0..5] of char;
  254.     dummy  : TOfStruct;         { Struct for OpenFile }
  255.     IOBuffer : PChar;
  256. Begin
  257.    GetMem(IOBuffer, $4000);
  258.    cnt    :=BlkSize div $4000;
  259.    Str(DiskNo, DiskNoStr);
  260.    StrCopy(FName, 'A:\DISK.');
  261.    strcat (FName, DiskNoStr);
  262.    {$I-}
  263.    Outf := OpenFile(FName, dummy, OF_CREATE or OF_READWRITE);
  264.    If (OutF=-1) then MessageBox(0, 'Fehler: OpenFile gescheitert', 'Backup', MB_oK);
  265.    result := $4000;
  266.    i      :=0;
  267.    while (i<cnt) and (result=$4000) do Begin
  268.       result := _lread(TmpFil, IOBuffer, $4000);
  269.       if (result<>0) and (result<>-1) then
  270.          _lwrite(Outf, IOBuffer, Result);
  271.       Inc(i);
  272.    End;
  273.  
  274.    _lclose(Outf);
  275.    {$I+}
  276.    FreeMem(IOBuffer, $4000);
  277. End;
  278.  
  279.  
  280.  
  281.  
  282.  
  283.  
  284.  
  285.  
  286. { --------------- Copy temporary File to Diskettes ------------------- }
  287. procedure TBckUp.CopyToDiskette(FName : PChar);
  288. var Answer : Integer;
  289.     DskFree: LongInt;
  290.     Listing: Text;              { A Backup Protocol Listing }
  291.     i      : Integer;
  292.     TmpFil : HFile;             { The tmporary compressed File }
  293.     TmpSize: LongInt;
  294.     dummy  : TOfStruct;         { Struct for OpenFile }
  295.  
  296. Begin
  297.   DskFree := -1;
  298.   Answer  := IDYES;
  299.  
  300.   TmpFil  := OpenFile(FName, dummy, OF_READ);
  301.   TmpSize := _llseek(TmpFil, 0, 2);
  302.              _llseek(TmpFil, 0, 0);
  303.  
  304.   if (TmpFil = -1) or (TmpSize<=0) then
  305.      MessageBox(HWindow, FName, 'Internal Error', MB_OK);
  306.  
  307.   while (Answer <> IDNO) and
  308.         (DskFree < Reserve) do Begin
  309.  
  310.      MessageBeep(0);
  311.      Answer := MessageBox(HWindow, 'It would be nice to insert the first Disk into Drive a:\',
  312.                                     'Backup', MB_YESNO or MB_ICONQUESTION);
  313.      if (Answer = IDYES) then Begin
  314.        DskFree := DiskFree(1);
  315.        if (DskFree>Reserve) then Begin
  316.  
  317.            { ---------- Write the Names of all the Files that have been Saves --------- }
  318.            Assign(Listing, 'A:\BACKUP.LOG');
  319.            rewrite(Listing);
  320.  
  321.            for i:=0 to SourceFiles.Count-1 do
  322.               writeln(Listing, PTFile(SourceFiles.At(I))^.Name);
  323.  
  324.            Close(Listing);
  325.  
  326.            { ---------- Create the Restore - Batch-File ------------------------------- }
  327.            Assign(Listing, 'a:\RESTORE.BAT');
  328.            rewrite(Listing);
  329.            writeln(Listing, '@echo off');
  330.            writeln(Listing, 'if %1X==ToCX goto ToC');
  331.            writeln(Listing, 'c:');
  332.            writeln(Listing, 'md \tmpr');
  333.            writeln(Listing, 'cd \tmpr');
  334.            writeln(Listing, 'Copy a:\restore.bat');
  335.            writeln(Listing, 'restore.bat ToC');
  336.            writeln(Listing, ':ToC');
  337.            for i:=1 to (TmpSize+DskFree-reserve-1) div (DskFree-Reserve) do Begin
  338.               if i<>0 then Begin writeln(Listing, 'echo Please  insert Next Diskette');
  339.                                  writeln(Listing, 'Pause');
  340.                            End;
  341.               writeln(Listing, 'copy a:\DISK.', i);
  342.            End;
  343.  
  344.            writeln(Listing, 'copy /b DISK.* ARC.LZH');
  345.            writeln(Listing, 'LHA E ARC.LZH');
  346.            writeln(Listing, ':Ende');
  347.  
  348.  
  349.            close(Listing);
  350.  
  351.            { ----------- Copy the Temporary File to the Diskettes --------------------- }
  352.            for i:=1 to (TmpSize+DskFree-Reserve-1) div (DskFree-Reserve) do Begin
  353.  
  354.               if i<>1 then Begin
  355.                           MessageBeep(0);
  356.                           MessageBox(HWindow, 'It would be nice to insert the next Disk into Drive a:\',
  357.                                        'Backup', MB_OK or MB_ICONQUESTION);
  358.                            End;
  359.  
  360.               CopyFileToDiskette(TmpFil, TmpSize, i, DskFree-Reserve);
  361.            End;
  362.        End;
  363.      End;
  364.   End;
  365.  
  366.   _lclose(tmpFil);
  367.   OpenFile(FName, dummy, OF_DELETE);
  368. End;
  369.  
  370.  
  371.  
  372. { Variables to exchange Informations between main and Callback }
  373. var CancelImmediatly : Boolean;              { True when running LHA and User selected to close it down }
  374.     CountDown        : Integer;              { Coounter for Callback Usage }
  375.  
  376. { ---------------- Let's define a Callback Function so the User won't be bored --- }
  377. function BckupCallbck(lhmsg : Integer; p : LPLHHEAD) : LHERR; export;
  378. var Msg : TMsg;
  379. Begin
  380.   Dec(Countdown);
  381.   if (CountDown<0) then Begin
  382.      CountDown:=100;
  383.      if (PeekMessage( Msg, 0, 0, 0, PM_REMOVE)) then Begin
  384.          if (not Application^.ProcessAppMsg(Msg)) then Begin
  385.              TranslateMessage(Msg);
  386.              DispatchMessage(Msg);
  387.          End;
  388.      End;
  389.      if CancelImmediatly
  390.        then BckupCallbck := LHN_STOP
  391.        else BckupCallbck := LHDefCallbck(lhmsg, p);
  392.   End
  393.   else      BckupCallbck := LHDefCallbck(lhmsg, p);
  394. End;
  395. exports  BckupCallbck;
  396.  
  397.  
  398. { ---------------- Abord Dialog Function: Cancel-Button pressed ------ }
  399. procedure TAbort.Cancel (var Msg: TMessage)  ;
  400. Begin
  401.     CancelImmediatly := TRUE;
  402. End;
  403.  
  404.  
  405. { ---------------- Start the BACKUP-Processing.... ------------------- }
  406.  
  407.  
  408. procedure TBckUp.Ok(var Msg: TMessage);
  409. var e         : LHERR;                  { Error Message form WLHA.DLL }
  410.     I         : Integer;
  411.     Options   : Integer;                { Options-Parameter for LHAppend }
  412.     FName     : array[0..144] of char;  { Our Temporary File Name }
  413.     ListBoxLine: Integer;
  414.     Abort     : PAbort;
  415. Begin
  416.    { Get a temporary Filename for Our Archiv }
  417.    GetTempFileName(#0, 'LZH', 0, FName);
  418.  
  419.    { Start the Processing if LHA-Archives via WLHA }
  420.    e := LHInit(HInstance);
  421.  
  422.    { Initializations }
  423.    CancelImmediatly := False;
  424.    CountDown        := 0;
  425.  
  426.    { Open an Abort Dialog Box }
  427.    Abort := PAbort( Application^.MakeWindow( new (PAbort, Init(@self, 'ABORT') ) ) ) ;
  428.  
  429.    if (e = LHE_OK) then Begin
  430.  
  431.       { ----------- Allow Background processing ------------------ }
  432.       LHSetCallback(@BckupCallbck);
  433.  
  434.       { ----------- Disable the direct closing of the main Window - }
  435.       EnableWindow(HWindow, False);
  436.  
  437.       I:=0;
  438.       while (i<SourceFiles.Count) and (e=LHE_OK) and not Cancelimmediatly do Begin
  439.  
  440.          { A Little bit of a Show for our Users }
  441.          ListBoxLine := SendMessage(Liste^.HWindow, LB_FINDSTRING, 0, LongInt(@PTFile(SourceFiles.At(I))^.Name) );
  442.          Liste^.SetSelIndex(ListBoxLine);
  443.  
  444.          { The First File need LGA_CREATEARCHIVE }
  445.          if (i=0) then Options := LHA_SHORTNAMES or LHA_CREATEARCHIV
  446.                   else Options := LHA_SHORTNAMES;
  447.  
  448.          { Let's give the Compression Task to WLHA.DLL }
  449.          e := LHAppend(FName, PTFile(SourceFiles.At(I))^.Name, Options);
  450.  
  451.          Inc(i);
  452.       End;
  453.  
  454.      { No more WLHA-Usage }
  455.      LHSetCallback(NIL);
  456.      LHEnd(hInstance);
  457.    End;
  458.  
  459.    { If there has been any Error, report it... }
  460.    if (e<>LHE_OK) then
  461.       LHErrMsgBox(e);
  462.  
  463.    { ----------- Ensable the normal Operation of the main Window - }
  464.    EnableWindow(HWindow, True);
  465.    SetFocus(HWindow);
  466.  
  467.    { Cancel the Abort Window if this has not already been done }
  468.    Abort^.CloseWindow;
  469.  
  470.    { Now: Copy the Temp-File to the Diskette }
  471.    if (e=LHE_OK) and not CancelImmediatly then Begin
  472.       CopyToDiskette(FName);
  473.       TDialog.Ok(Msg);
  474.    End;
  475. End;
  476.  
  477.  
  478.  
  479.  
  480.  
  481.  
  482. { ---------------- Interesting Part ... -------------------------------- }
  483. procedure TBckup.SetupWindow;
  484. var rc : TRect;
  485. Begin
  486.    TDialog.SetupWindow;
  487.  
  488.    GetClientRect(HWindow, rc);
  489.  
  490.    { --------- Create a Listbox with our File names ---------------------}
  491.    Liste := PListBox(Application^.MakeWindow(new (PListBox, Init(@self, IDFILES, 5, 5, rc.right-10, rc.bottom-60) ))) ;
  492.  
  493.    { First, it would be a good Idea to find out, what the User wants to Backup,
  494.      so let's look first for a Command Line parameter, and if there is none,
  495.      we use the Windows 3.1 COMMDLG-API }
  496.  
  497.    if (ParamCount > 0)  { Any parameters on CommandLine ? }
  498.       then FilesFromCommandLine
  499.       else FilesFromCommDlg;
  500.  
  501.    { ---------- Anyway: Do you like Programs that don't accept Files from WinFile ? ---- }
  502.    DragAcceptFiles(HWindow, TRUE);  { So let's accept Files }
  503.  
  504. End;
  505.  
  506.  
  507. { ------------------------ Main Program -------------------------------- }
  508. var App : TApp;
  509.  
  510. Begin
  511.  
  512.     { In the Main Program we'll only open a litte Listbox-Window...
  513.       nothing special...
  514.  
  515.       The Interesting parts you'l find in TBckup.SetupWindow
  516.     }
  517.  
  518.     SourceFiles.Init(100,100);
  519.  
  520.     App.Init('Test ');
  521.     App.Run;
  522.     App.Done;
  523.  
  524. End.
  525.